﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using tuwien.auto.eibclient;
using KNXFramework.Logging;

namespace KNXFramework.KNXObjects.ValueObjects
{
    internal class ValueObjectValue : IValueObject
    {
        private double m_Value;
        #region Constructors
        public ValueObjectValue(string value)
        {
            if (!double.TryParse(value, out m_Value))
                throw new ApplicationException("ValueObjectValue: cannot parse value to double. Val : " + value);

            if (m_Value > 670760.96 || m_Value < -671088.64)
                throw new ApplicationException("ValueObjectValue: Value must be between -671088.64 and 670760.96. Val : " + m_Value);

        }
        public ValueObjectValue(EIBBuffer buffer)
        {
            if (buffer.data.Length < 4)
            {
                CustomLogger.WriteErrorEntry("Invalid packet received for ValueObject (too short)");
                return;
            }
            double newValue;
            int d1 = buffer.data[2] * 256 + buffer.data[3];
            int m = d1 & 0x7ff;
            if ((d1 & 0x8000) == 0x8000)
                m |= ~0x7ff;
            int ex = (d1 & 0x7800) >> 11;
            newValue = ((double)m * (1 << ex) / 100);
            m_Value = newValue;
        }
        #endregion

        public override string ToString()
        {
            return m_Value.ToString("#.########");
        }

        #region IValueObject Members

        public void AdaptBufferBeforeSending(bool isWrite, tuwien.auto.eibclient.EIBBuffer buffer)
        {
            byte[] b = new byte[4];
            b[0] = 0;
            b[1] = buffer.data[1];
            int ex = 0;
            int m = Convert.ToInt32(m_Value * 100);
            if (m < 0)
            {
                m = -m;
                while (m > 2048)
                {
                    m = m >> 1;
                    ex++;
                }
                m = -m;
                b[2] = Convert.ToByte(((m >> 8) & 0x07) | ((ex << 3) & 0x78) | (1 << 7));
            }
            else
            {
                while (m > 2047)
                {
                    m = m >> 1;
                    ex++;
                }
                b[2] = Convert.ToByte(((m >> 8) & 0x07) | ((ex << 3) & 0x78) | (1 << 7));
            }
            b[3] = Convert.ToByte(m & 0xff);
            buffer.data = b;
        }

        #endregion

        #region IEquatable<IValueObject> Members

        public bool Equals(IValueObject other)
        {
            ValueObjectValue otherVal = other as ValueObjectValue;
            bool equality = false;
            if (otherVal != null)
                equality = m_Value.Equals(otherVal.m_Value);
            return equality;
        }

        #endregion

    }
}
